/*================================================================
*   Copyright (C) 2021 Sangfor Ltd. All rights reserved.
*   
*   文件名称：UserManager.hpp
*   创 建 者：wudu
*   创建日期：2021年07月09日
*   描    述：
*
================================================================*/
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <cstring>

#include "../connectinfo.hpp"

using namespace std;

class UserInfo
{
    public:
        UserInfo(const string& nickname, string& school, string& passwd, uint32_t userid)
        {
            nickname_ = nickname;
            school_ = school;
            passwd_ = passwd;
            userid_ = userid;

            status_ = RegisterFailed;

            //memset((char*)udp_addr_, '\0', sizeof(udp_addr_));
            addr_len_ = -1;
        }

        string& GetPasswd()
        {
            return passwd_;
        }

        void SetUserStatus(int sta)
        {
            status_ = sta;
        }

        int GetUserStatus()
        {
            return status_;
        }

        void SetUdpAddr(struct sockaddr_in* udp_addr)
        {
            memcpy(&udp_addr_, udp_addr, sizeof(struct sockaddr_in));
        }

        void SetUdpAddrLen(socklen_t len)
        {
            addr_len_ = len;
        }

        struct sockaddr_in& GetUdpAddr()
        {
            return udp_addr_;
        }

        socklen_t GetUdpAddrLen()
        {
            return addr_len_;
        }

    private:
        string nickname_;
        string passwd_;
        string school_;
        uint32_t userid_;

        int status_;

        struct sockaddr_in udp_addr_;
        socklen_t addr_len_;
};

class UserManager
{
    public:
        UserManager()
        {
            map_.clear();
            prepare_id_ = 1;
            pthread_mutex_init(&map_lock_, NULL);

            online_vec_.clear();
        }
        ~UserManager()
        {
            pthread_mutex_destroy(&map_lock_);
        }

        /*
         * 1.user_id 是出参， 返回给上层的调用者
         * */

        int RegisterUserInfo(struct RegInfo& ri, uint32_t* user_id)
        {
            /*
             * 1.先判断密码是否有效（长度）
             * 2.构造userinfo
             * 3.将userinfo 放到map当中
             * 4.准备返回给上层调用者 的userid
             * */
            if(strlen(ri.passwd_) == 0)
            {
                printf("密码长度不对， 注册失败");
                return -1;
            }

            string nickname, school, passwd;
            nickname = ri.nickname_;
            school = ri.school_;
            passwd = ri.passwd_;

            pthread_mutex_lock(&map_lock_);
            UserInfo ui(nickname, school, passwd, prepare_id_);
            *user_id = prepare_id_;
            ui.SetUserStatus(RegisterSuccess);
            map_.insert(std::make_pair(prepare_id_, ui));
            prepare_id_++;
            pthread_mutex_unlock(&map_lock_);

            return 0;
        }

        int LoginCheck(struct LoginInfo& li)
        {
            /*
             * 1.判断密码长度
             * 2.判断用户是否在map
             *    如果不在： 返回登录失败
             *    在：
             *       比对密码
             *          密码正确：登录成功
             *          密码错误：登录失败
             * */
            if(strlen(li.passwd_) == 0)
            {
                return -1;
            }

            unordered_map<uint32_t, UserInfo>::iterator iter;

            pthread_mutex_lock(&map_lock_);
            iter = map_.find(li.userid_);
            if(iter == map_.end())
            {
                pthread_mutex_unlock(&map_lock_);
                return -2;
            }

            string send_passwd = li.passwd_;

            if(send_passwd != iter->second.GetPasswd())
            {
                return -3;
            }

            iter->second.SetUserStatus(LoginSuccess);
            pthread_mutex_unlock(&map_lock_);
            return 0;
        }

        int IsLogin(uint32_t userid, struct sockaddr_in* udp_addr, socklen_t addr_len)
        {
            pthread_mutex_lock(&map_lock_);
            unordered_map<uint32_t, UserInfo>::iterator iter = map_.find(userid);
            if(iter == map_.end())
            {
                pthread_mutex_unlock(&map_lock_);
                return -1;
            }

            int flag = -1;
            if(iter->second.GetUserStatus() <= LoginFailed)
            {
                flag = -2;
            }
            else if(iter->second.GetUserStatus() == LoginSuccess)
            {
                flag = 0;
                //保存udp地址信息
                iter->second.SetUdpAddr(udp_addr);
                iter->second.SetUdpAddrLen(addr_len);
                //更改用户状态为 在线状态
                iter->second.SetUserStatus(Online);

                online_vec_.push_back(iter->second);
            }

            if(iter->second.GetUserStatus() == Online)
            {
                pthread_mutex_unlock(&map_lock_);
                return 0;
            }
            pthread_mutex_unlock(&map_lock_);
            return flag;
        }

        void GetOnlineUser(vector<UserInfo>* online_user)
        {
            *online_user = online_vec_; 
        }
    private:
        //stl 并不保证线程安全
        unordered_map<uint32_t, UserInfo> map_;
        //预分配的用户id
        uint32_t prepare_id_;
        pthread_mutex_t map_lock_;

        vector<UserInfo> online_vec_;
};
